#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Fri Aug 29 17:19:15 2025

@author: ulyanov
"""

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import pygame
import sys
import random
from config import *
from snake import Snake
from food import Food, SpecialFood

class Game:
    def __init__(self, selected_map=1):
        pygame.init()
        self.screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
        pygame.display.set_caption("贪吃蛇")
        self.clock = pygame.time.Clock()
        self.font = pygame.font.SysFont(None, 36)
        
        # 调试用变量
        self.debug = True  # 开启调试模式
        
        # 难度相关设置
        self.base_fps = FPS  # 基础帧率
        self.max_speed_level = 5  # 最大速度等级
        self.speed_level = 1  # 当前速度等级
        self.last_speed_increase = pygame.time.get_ticks()  # 上次提速时间
        self.speed_increase_interval = 30000  # 提速间隔(毫秒)
        
        self.selected_map = selected_map  # 存储选中的地图
        self.stones = []  # 存储石头位置
        
        # 先创建蛇对象，再生成石头
        self.snake = Snake()
        
        # 生成对应地图的石头
        if self.selected_map in [2, 3]:  # 地图2和3有石头
            self.generate_stones()
        
        # 游戏状态变量
        self.normal_food_eaten = 0  # 已吃普通食物数量
        self.special_food = None
        self.score = 0  # 分数
        self.game_over = False
        self.game_start_time = pygame.time.get_ticks()  # 游戏开始时间
        
        # 长度增长相关变量
        self.last_growth_score = 0  # 记录上次增长时的分数
        self.growth_interval = 30   # 每30分增长一次
        
        # 食物相关设置
        self.food_list = []  # 存储多个普通食物
        self.current_food_count = 1  # 当前食物数量
        self.update_food_count()  # 更新食物数量
        self.generate_food()  # 生成初始食物
    
    def generate_stones(self):
        """根据所选地图生成不同的石头布局"""
        if self.debug:
            print(f"生成地图{self.selected_map}的石头...")
        
        self.stones = []  # 清空现有石头
        
        if self.selected_map == 2:
            # 地图2的石头布局
            # 边缘石头
            for x in range(0, SCREEN_WIDTH, GRID_SIZE * 3):
                self.stones.append((x, 0))  # 顶部边缘
                self.stones.append((x, SCREEN_HEIGHT - GRID_SIZE))  # 底部边缘
            
            for y in range(GRID_SIZE * 3, SCREEN_HEIGHT - GRID_SIZE * 3, GRID_SIZE * 3):
                self.stones.append((0, y))  # 左边缘
                self.stones.append((SCREEN_WIDTH - GRID_SIZE, y))  # 右边缘
            
            # 中间随机石头
            max_stones = 10
            attempts = 0
            while len(self.stones) < max_stones and attempts < 100:
                x = random.randint(2, (GRID_WIDTH - 3)) * GRID_SIZE
                y = random.randint(2, (GRID_HEIGHT - 3)) * GRID_SIZE
                stone_pos = (x, y)
                
                if stone_pos not in self.stones and stone_pos not in self.snake.positions:
                    self.stones.append(stone_pos)
                attempts += 1
        
        elif self.selected_map == 3:
            # 地图3：中心正方形盒子，四条边各有一个开口
            
            # 关键参数 - 确保与网格对齐
            box_grid_size = 8  # 盒子大小（网格数）
            opening_grid_width = 1  # 开口宽度（网格数）
            
            # 计算实际像素尺寸
            grid_size = GRID_SIZE  # 这里使用局部变量，基于导入的常量
            box_pixel_size = box_grid_size * grid_size
            
            # 计算屏幕中心（确保与网格对齐）
            center_x = (SCREEN_WIDTH // (2 * grid_size)) * grid_size
            center_y = (SCREEN_HEIGHT // (2 * grid_size)) * grid_size
            
            # 计算盒子边界（确保与网格对齐）
            box_left = center_x - (box_pixel_size // 2)
            box_top = center_y - (box_pixel_size // 2)
            box_right = box_left + box_pixel_size - grid_size
            box_bottom = box_top + box_pixel_size - grid_size
            
            # 计算每条边的开口位置（精确到网格，确保在中点）
            # 上边开口（中点）
            top_openings = [(center_x, box_top)]
            
            # 右边开口（中点）
            right_openings = [(box_right, center_y)]
            
            # 下边开口（中点）
            bottom_openings = [(center_x, box_bottom)]
            
            # 左边开口（中点）
            left_openings = [(box_left, center_y)]
            
            # 所有开口位置
            all_openings = top_openings + right_openings + bottom_openings + left_openings
            
            if self.debug:
                print(f"地图3参数: 中心({center_x},{center_y}), 盒子范围({box_left},{box_top})-({box_right},{box_bottom})")
                print(f"开口位置: {all_openings}")
            
            # 生成上边石头（排除开口）
            for x in range(box_left, box_right + grid_size, grid_size):
                pos = (x, box_top)
                if pos not in top_openings:
                    self.stones.append(pos)
            
            # 生成右边石头（排除开口）
            for y in range(box_top, box_bottom + grid_size, grid_size):
                pos = (box_right, y)
                if pos not in right_openings:
                    self.stones.append(pos)
            
            # 生成下边石头（排除开口）
            for x in range(box_left, box_right + grid_size, grid_size):
                pos = (x, box_bottom)
                if pos not in bottom_openings:
                    self.stones.append(pos)
            
            # 生成左边石头（排除开口）
            for y in range(box_top, box_bottom + grid_size, grid_size):
                pos = (box_left, y)
                if pos not in left_openings:
                    self.stones.append(pos)
            
            # 盒子周围添加少量石头
            surrounding_stones = 6
            attempts = 0
            while len(self.stones) < (box_grid_size * 4 - 4) + surrounding_stones and attempts < 100:
                x = random.randint(0, GRID_WIDTH - 1) * grid_size
                y = random.randint(0, GRID_HEIGHT - 1) * grid_size
                stone_pos = (x, y)
                
                # 确保石头不在盒子上、开口处或蛇身上
                if (stone_pos not in self.stones and
                    stone_pos not in self.snake.positions and
                    stone_pos not in all_openings and
                    not (box_left <= stone_pos[0] <= box_right and 
                         box_top <= stone_pos[1] <= box_bottom)):
                    self.stones.append(stone_pos)
                attempts += 1
        
        if self.debug:
            print(f"生成了 {len(self.stones)} 个石头")
    
    def update_food_count(self):
        """根据当前分数更新食物数量"""
        new_count = (self.score // 100) + 1
        max_possible_food = (GRID_WIDTH * GRID_HEIGHT) // 10
        self.current_food_count = min(new_count, max_possible_food)
        
        if self.debug and new_count > 1:
            print(f"食物数量已更新为: {self.current_food_count} (当前分数: {self.score})")
    
    def generate_food(self):
        """生成指定数量的食物"""
        self.food_list = []
        avoid_positions = self.snake.positions + self.stones
        if self.special_food:
            avoid_positions.append(self.special_food.position)
            
        for _ in range(self.current_food_count):
            food = Food()
            food.spawn(avoid_positions)
            self.food_list.append(food)
            avoid_positions.append(food.position)
    
    def check_speed_increase(self):
        """检查是否需要提升速度"""
        current_time = pygame.time.get_ticks()
        if (current_time - self.last_speed_increase > self.speed_increase_interval and 
            self.speed_level < self.max_speed_level):
            self.speed_level += 1
            self.last_speed_increase = current_time
            if self.debug:
                print(f"速度提升! 当前等级: {self.speed_level}, 帧率: {self.get_current_fps()}")
    
    def get_current_fps(self):
        """计算当前帧率"""
        return self.base_fps + (self.speed_level - 1) * 2
    
    def handle_events(self):
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                return "quit"
            if event.type == pygame.KEYDOWN:
                if self.game_over:
                    if event.key == pygame.K_r:
                        return "restart"
                    elif event.key == pygame.K_s:
                        return "select_map"
                else:
                    self.snake.change_direction(event.key)
                if event.key == pygame.K_d:
                    self.debug = not self.debug
                    print(f"调试模式: {'开启' if self.debug else '关闭'}")
        return "continue"
    
    def check_length_growth(self):
        """检查是否需要增加蛇的长度"""
        growth_count = (self.score - self.last_growth_score) // self.growth_interval
        
        if growth_count > 0:
            for _ in range(growth_count):
                self.snake.grow()
                self.last_growth_score += self.growth_interval
                if self.debug:
                    print(f"蛇长度增加！当前分数: {self.score}, 长度: {len(self.snake.positions)}")
                    
    def check_collisions(self):
        head = self.snake.positions[0]
        
        # 检查撞墙
        if (head[0] < 0 or head[0] >= SCREEN_WIDTH or
            head[1] < 0 or head[1] >= SCREEN_HEIGHT):
            self.game_over = True
        
        # 检查撞自己
        if head in self.snake.positions[1:]:
            self.game_over = True
        
        # 检查撞石头
        if self.selected_map in [2, 3] and head in self.stones:
            self.game_over = True
    
    def update(self):
        if not self.game_over:
            self.check_speed_increase()
            self.snake.move()
            head = self.snake.positions[0]
            
            # 检查吃普通食物
            food_eaten = False
            for food in self.food_list[:]:
                if food.is_eaten(head):
                    self.score += 10
                    self.normal_food_eaten += 1
                    self.food_list.remove(food)
                    food_eaten = True
                    if self.debug:
                        print(f"吃到普通食物! 分数: {self.score}")
            
            # 生成新食物
            if not self.food_list:
                self.update_food_count()
                self.generate_food()
                
                # 检查生成特殊食物
                if self.normal_food_eaten % 5 == 0 and not self.special_food:
                    if self.debug:
                        print(f"生成特殊食物 (已吃{self.normal_food_eaten}个普通食物)")
                    
                    self.special_food = SpecialFood()
                    max_attempts = 100
                    attempts = 0
                    avoid_positions = self.snake.positions + self.stones
                    for food in self.food_list:
                        avoid_positions.append(food.position)
                        
                    while self.special_food.position in avoid_positions and attempts < max_attempts:
                        self.special_food.spawn(avoid_positions)
                        attempts += 1
            
            # 检查吃特殊食物
            if self.special_food and self.special_food.is_eaten(head):
                self.score += 100
                if self.debug:
                    print(f"吃到特殊食物! 新分数: {self.score}")
                self.special_food = None
            
            # 移除蛇尾
            if not food_eaten and not (self.special_food and self.special_food.is_eaten(head)):
                self.snake.positions.pop()
            
            # 检查特殊食物过期
            if self.special_food and self.special_food.is_expired():
                if self.debug:
                    print("特殊食物已过期")
                self.special_food = None
            
            self.check_length_growth()
            self.check_collisions()
    
    def draw(self):
        self.screen.fill(BLACK)
        
        # 绘制石头
        if self.selected_map in [2, 3]:
            for stone in self.stones:
                pygame.draw.rect(self.screen, GRAY, 
                               (stone[0], stone[1], GRID_SIZE, GRID_SIZE))
        
        self.snake.draw(self.screen)
        
        # 绘制普通食物
        for food in self.food_list:
            food.draw(self.screen)
        
        # 绘制特殊食物
        if self.special_food:
            self.special_food.draw(self.screen)
            if self.debug:
                remaining = self.special_food.duration - (pygame.time.get_ticks() - self.special_food.spawn_time)
                timer_text = self.font.render(f"Care!: {remaining//1000}s", True, YELLOW)
                self.screen.blit(timer_text, (10, 70))
        
        # 绘制分数和速度
        if self.font:
            score_text = self.font.render(f"Score: {self.score}", True, WHITE)
            self.screen.blit(score_text, (10, 10))
            
            speed_text = self.font.render(f"Speed: Lv{self.speed_level}", True, WHITE)
            self.screen.blit(speed_text, (10, 40))
        
        # 游戏结束文字
        if self.game_over and self.font:
            game_over_text = self.font.render("GAME OVER!", True, RED)
            restart_text = self.font.render("R to restart, S to select a map", True, WHITE)
            
            text_rect = game_over_text.get_rect(center=(SCREEN_WIDTH//2, SCREEN_HEIGHT//2 - 30))
            restart_rect = restart_text.get_rect(center=(SCREEN_WIDTH//2, SCREEN_HEIGHT//2 + 30))
            
            self.screen.blit(game_over_text, text_rect)
            self.screen.blit(restart_text, restart_rect)
        
        pygame.display.update()
    
    def reset(self):
        if self.debug:
            print("游戏重置")
        self.snake.reset()
        self.speed_level = 1
        self.last_speed_increase = pygame.time.get_ticks()
        if self.selected_map in [2, 3]:
            self.stones = []
            self.generate_stones()
        self.current_food_count = 1
        self.food_list = []
        self.generate_food()
        self.special_food = None
        self.normal_food_eaten = 0
        self.score = 0
        self.last_growth_score = 0
        self.game_over = False
        self.game_start_time = pygame.time.get_ticks()
    
    def run(self):
        running = True
        if self.debug:
            print("游戏开始运行...")
        while running:
            event_result = self.handle_events()
            
            if event_result == "quit":
                running = False
                return "quit"
            elif event_result == "restart":
                self.reset()
            elif event_result == "select_map":
                return "select_map"
            
            self.update()
            self.draw()
            self.clock.tick(self.get_current_fps())
        
        pygame.quit()
        return "quit"

if __name__ == "__main__":
    game = Game()
    game.run()